using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization; 

namespace XRM.Security.WebUI.Helpers
{
    public static class XmlSerializerHelper
    {
        public static XmlSerializer GetXmlSerializer<T>()
        {
            return new XmlSerializer(typeof (T));
        }

        public static T Deserialize<T>(this StringReader reader )
        {
            var serializer = new XmlSerializer(typeof (T));
            try
            {
                return (T) serializer.Deserialize(reader);
            }
            catch (Exception e)
            { 
                return default(T);
            }
        }

        public static T Deserialize<T>(this Stream reader)
        {
            var serializer = new XmlSerializer(typeof (T));
            return (T) serializer.Deserialize(reader);
        }


        public static string SerializeUTF8(this XmlSerializer @this, object obj, bool needRemoveStandartNamespaces = false)
        {
            using (var memoryStream = new MemoryStream())
            {
                var xmlWriterSettings = new XmlWriterSettings
                {
                    Encoding = new UTF8Encoding(true),
                    Indent = true,
                    OmitXmlDeclaration = false
                };
                var xmlTextWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
                if (needRemoveStandartNamespaces)
                {
                    var xns = new XmlSerializerNamespaces();
                    xns.Add("", "");
                    @this.Serialize(xmlTextWriter, obj, xns);
                }
                else
                {
                    @this.Serialize(xmlTextWriter, obj);
                }
                return Encoding.UTF8.GetString(memoryStream.ToArray());
            }
        }

        public static string SerializeUTF8<T>(T obj)
        {
            return new XmlSerializer(typeof (T)).SerializeUTF8(obj);
        }

        public static string Serialize(this XmlSerializer @this, object obj)
        {
            using (var stringWriter = new StringWriter())
            {
                @this.Serialize(stringWriter, obj);
                return stringWriter.ToString();
            }
        }

        public static byte[] SerializeBytes(this XmlSerializer @this, object obj)
        {
            var memoryStream = new MemoryStream();
            @this.Serialize(memoryStream, obj);
            return memoryStream.ToArray();
        }

        public static byte[] SerializeBytes<T>(T obj)
        {
            using (var memoryStream = new MemoryStream())
            {
                var xmlWriterSettings = new XmlWriterSettings
                {
                    Encoding = new UTF8Encoding(true),
                    Indent = true,
                    OmitXmlDeclaration = false
                };
                var xmlTextWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
                var ser = new XmlSerializer(typeof (T));
                ser.Serialize(xmlTextWriter, obj);
                return memoryStream.ToArray();
            }
        }

        public static byte[] SerializeBytesUtf8<T>(T obj)
        {
            return SerializeBytes(obj);
        }

        public static object Deserialize(this XmlSerializer @this, string str)
        {
            return @this.Deserialize(new StringReader(str));
        }

        public static object DeserializeUTF8(this XmlSerializer @this, string str)
        {
            return @this.Deserialize(Encoding.UTF8.GetBytes(str));
        }

        public static T DeserializeUTF8<T>(string str)
        {
            var ser = new XmlSerializer(typeof (T));
            return (T) ser.DeserializeUTF8(str);
        }

        public static T Deserialize<T>(string str)
        {
            var ser = new XmlSerializer(typeof (T));
            return (T) ser.Deserialize(str);
        }

        public static T Deserialize<T>(this byte[] bytes)
        {
            var ser = new XmlSerializer(typeof (T));
            var reader = XmlReader.Create(new MemoryStream(bytes), new XmlReaderSettings());
            return (T) ser.Deserialize(reader);
        }

        public static T Deserialize<T>(XmlReader reader)
        {
            var ser = new XmlSerializer(typeof (T));
            return (T) ser.Deserialize(reader);
        }

        public static string Serialize<T>(T obj, bool needRemoveStandartNamespaces = false)
        {
            var ser = new XmlSerializer(typeof (T));
            return ser.SerializeUTF8(obj, needRemoveStandartNamespaces);
        }

        public static object Deserialize(this XmlSerializer @this, byte[] bytes)
        {
            var memoryStream = new MemoryStream(bytes);
            return @this.Deserialize(memoryStream);
        }
    }
}